What is a variable? A variable is a word in the programming language that stands for something. Most of the special variables in World Builder stand for a specific, fixed thing. For instance, the variable PLAYER@ stands for the player character, regardless of what that character's name is. The variable LOOP# stands for the number of commands given in the current scene. It is a way of counting and storing a number, in this case the number of commands given by the player in a scene. It can't be used for anything else.
User variables stand for numbers. But with user variables, the programmer gets to decide what number is stored in the variable, and what it stands for. This gives the programmer tremendous freedom to control the events of the game.
A user variable is designated by a letter/number combination, using a single uppercase letter (A-Z) followed by a single digit (1-9). The standard numeric sign is also a part of the variable name. Here are some examples of user variables:
A1# M7# H3# L9#
These are just the names of the variables. You get to decide what number each name stands for. To make a variable stand for a specific number, use the LET statement:
LET{A1#=100}
In the above example, the variable A1# is assigned a value of 100. Numbers assigned to variables must be whole numbers in the range from -32768 to 32768. Do not use commas in the number.
You can change the number of a variable at any time.
"What good is this?" you might ask. Well, by using variables you can keep track of what the player has done during the game. Suppose you want the player to get new information everytime he talks to a certain character. How would you (or the game) know if this is the first time the player has spoken to that character, or the fifth time? Only by using a variable to keep track of it, like this:
IF{TEXT$=TALK}OR{TEXT$=INFO}OR{TEXT$=ASK}THEN
IF{M1#<1}THEN
PRINT{INNKEEPER: "I heard that some bandits hideout in the canyons to the north of town. Watch your step if you travel that way, stranger."}
LET{M1#=1}
EXIT
IF{M1#=1}THEN
PRINT{INNKEEPER: "Last winter an old man was in here talking about a treasure hidden in the castle ruins. No one's ever found it though."}
LET{M1#=2}
EXIT
IF{M1#=2}THEN
PRINT{INNKEEPER: "My grandfather was there the day the old king died. He said the king's last words were, 'Bite the wax tadpole.'"}
LET{M1#=3}
EXIT
PRINT{INNKEEPER: "Sorry young fella, I haven't heard anything new lately."}
EXIT
In this example, everytime the player enters TALK (or a similar command), the program checks to see what the variable M1# is set at. The first nested IF/THEN statement determines whether the variable is less than one. (Variables that haven't previously been set do not equal any number, including zero, so this is the best way to test for an unset variable.)
If M1# is less than one, then the program prints the text giving the player the first message. A LET statement then updates the variable, making it equal one. The program then exits.
The next time the player enters the TALK command, the program finds that M3# is not less than one, so it skips the first IF/THEN statement and moves on to the second one. This next statement tests to see if the variable equals one. Since the variable now equals one, the program displays the second message for the player, and again updates the variable to equal 2, and exits.
You can continue like this as many times as necessary, within the limits of the scene code capacity. At the end, there is a default message that will be automatically printed anytime the variable is not equal to a number previously handled.
That arrow-like symbol (<) is called a comparison operator. It means "less than". An arrow facing the other direction (>) means "greater than." Both symbols can also mean "does not equal" or "does not have," depending on how they are used. These two symbols can be used for other things besides numbers:
IF{KNIFE>PLAYER@}THEN
This statement tests whether the player has the knife. Literally, this statement says "If the knife does not equal the player, then..." In this case, "does not equal" means the knife is not in the player's possession. You can also use = to see if an object is in the player's possession, or in a scene, etc. Whether you use (>) or (=) will depend on the specific circumstances involved. Below are some examples of ways to use these comparison operators, and their meanings:
IF{MONSTER@=SCENE@}THEN ("If any non-player character is in the
current scene....")
IF{SHOTGUN>THUG}THEN ("If the character called 'thug' does not have the
shotgun...")
IF{INNKEEPER=SCENE@}THEN ("If the character or object called 'innkeeper'
is in the current scene...")
IF{LAMP>PLAYER@}THEN ("If the player does not have the lamp...")
IF{H2#<4}THEN ("If variable H2# is less than four...")
IF{D7#>0}THEN ("If variable D7# is more than zero...")
IF{B1#=20}AND{C1#<1}THEN ("If variable B1 equals 20, AND variable C1 is
less than one [or unset]...)
Notice that both conditions must be true.
IF{MOOSE=SCENE@}OR{SQUIRREL=SCENE@}THEN
("If the object or character called 'moose' is in
the scene, OR the object or character called
'squirrel' is in the scene...")
Notice that if either of these conditions is true,
the statement will be executed.
When handling commands, there are two more comparison operators: (==) and (>>). Using a pair of equals signs means that the command must match EXACTLY for the statement to be true. Using a pair of "greater than" signs means the statement is true only if the command does NOT match exactly. Remember, these are used only for text. Here are some examples:
IF{TEXT$==EAT FOOD}THEN
IF{TEXT$>>PASSWORD}THEN
In the first example, the player would have to enter "eat food" exactly like that. Anything else, such as "eat some food" would not register. There are not many ways in which this kind of command structure is useful.
In the second example, the statement is true if the player enters anything other than "password" exactly that way. This is also something that has limited usefulness.
Anyway, let's get back to user variables. We've seen how a variable can be set to count the times that a player talks to another character, and how that can be used to control the character's replies. What other things are variables good for? Well, let's say you want the player to get "hungry" on a regular basis. At some point in the very beginning of the game, you'd need to set a variable to represent the player's apetite:
LET{H1#=95}
This gives the player a "full stomach" to start with. (It can be any number, not just 95.) From here you need a way of reducing that number as the player moves through the game. This will simulate the player's growing hunger with the passing of time. Since there is no clock in a WB game, the easiest way to simulate this is by subtracting one from the variable everytime the player enters a scene. So in each scene you'd need something like this at the top of the scene code:
IF{LOOP#=0}THEN
LET{H1#=H1#-1}
END
With this code, the program will subtract one from the variable H1# when the player enters the scene. Once the player makes any move or command, the loop number increases beyond zero, and the statement is ignored. If the player leaves the scene, then returns, the loop is reset to zero, and one more point is subtracted from H1#.
Now we have a way of counting down the variable that represents the player's need for food. But how do you put it to use?
Since the code needed to tell the player when he's hungry is a bit longer, it's best to put it in the global code. At the top of the global code, you'd need something like this:
IF{LOOP#=0}THEN
IF{H1#<1}THEN
PRINT{You just died of starvation!}
MOVE{PLAYER@}TO{STORAGE@}
EXIT
IF{H1#<20}THEN
PRINT{You need to eat soon.}
END
END
With this code, if the loop number is zero (the player just entered a scene), the program then finds out if variable H1 is less than one. If it is, it means the player has died of starvation. A message is displayed, and the player is moved to STORAGE@, ending the game. Since nothing more should happen, the statement is closed with EXIT.
If variable H1 is not less than one, then the next IF/THEN statement checks to see if the variable is less than 20. If it is any number below 20, a message is printed telling the player to find some food. Since the player is still alive, there's no need to stop there, so the statement closes with END. This allows the program to check the rest of the global code to see if anything else needs to happen.
Now we have a way of notifying the player when his "hunger" points are getting low, and a way to kill him when it reaches zero or less. Next we need a way for him to restore his hunger points by eating. If the player can carry food with him, the "eating" code should be in the Global code. If the player can only eat at a designated location, then you could put the "eat" code in that scene. In either case, here's what the code might look like:
IF{TEXT$=EAT}THEN
IF{TEXT$=FOOD}THEN
IF{FOOD=PLAYER@}THEN
SOUND{CHEWING}
MOVE{FOOD}TO{STORAGE@}
LET{H1#=95}
PRINT{The food satisfies your hunger.}
EXIT
PRINT{You don't have any food.}
EXIT
PRINT{Eat what?}
EXIT
The first statement tests to see if the player has entered the word "eat". It could be just the word eat, or it could be part of an entire sentence. In either case, the statement would be true, and the program goes to the second statement, which tests to see if the word "food" was also entered. If the word "food" was not entered, then both the second and third statements are ignored, and the player is asked to specify what he wants to eat.
If both words ("eat" and "food"), then the third statement tests to see if the player has the food in his possession. If this is true, then a chewing sound is played, the food is moved to STORAGE@, and the variable representing the player's hunger points is restored.
If the player does not have the food, then the third statement is ignored, and a message is printed telling the player that he doesn't have the food.
(Anytime you have one or more statements within another statement, it is called a nested statement.)
Now let's suppose you want the player to get more than one meal from his supply of food. For this you'd need another variable:
IF{TEXT$=EAT}THEN
IF{TEXT$=FOOD}THEN
IF{FOOD=PLAYER@}THEN
SOUND{CHEWING}
LET{H1#=95}
LET{F1#=F1#-1}
PRINT{The food satisfies your hunger.}
IF{F1#<1}THEN
MOVE{FOOD}TO{STORAGE@}
PRINT{You food has run out.}
EXIT
EXIT
PRINT{You don't have any food.}
EXIT
PRINT{Eat what?}
EXIT
In this case, variable F1 is used to represent the amount of food the player has. Everytime the player eats, the variable is reduced by one. After executing the "eat" code, a fourth IF/THEN statement checks to see if the variable representing the food is less than one. If variable is less than one, then the food is moved to STORAGE@ and a message is displayed telling the player that his food has run out.
Of course, when the player first gets the food, you'd have to set the variable F1# to a number representing the number of meals he can get from it. And after the food runs out, when he finds more food later (really the same "food" object), you'd have to reset the variable.
---------------------------------------------
In these examples, the variables representing the player's hunger, and the meals in his food supply, are first set, then gradually reduced. This works fine. However, you could easily do it the other way around: Instead of setting the variables and then reducing them, you could just add to the variables each time. In this way, you could skip the initial step of setting the variables. Then instead of killing the player when his hunger goes down to zero, you could kill him when it goes up to 95 (or whatever.)
And instead of his food running out when the meals number goes down to zero, you could have it run out when the meals number goes up to 3 (or whatever).
---------------------------------------------
Here's another way you can use variables. Suppose you want the player to use a computer, but only after a chip has been installed. Use a variable to find out whether or not the player has installed the chip:
IF{TEXT$=USE}THEN
IF{TEXT$=COMPUTER}THEN
IF{C1#=1}THEN
SOUND{BEEP}
MOVE{SCREEN.1}TO{SCENE@}
PRINT{The computer screen lights up, displaying a message:
PRINT{COMPUTER: "Greetings! Click the screen to continue."}
EXIT
PRINT{Nothing happens when you push the startup button on the computer.}
EXIT
IF{TEXT$=CHIP}THEN
IF{CHIP=PLAYER@}THEN
SOUND{CLICK}
MOVE{CHIP}TO{STORAGE@}
LET{C1#=1}
PRINT{The chip is now in the computer.}
EXIT
PRINT{You don't have the chip.}
EXIT
END
The first statement here tests to see if the player has entered the word "use." If he has, then the second statement checks to see if he has also entered the word "computer." If the player has entered both words ("use" and "computer"), then the third statement tests to see if the value of variable C1 is one. If C1# equals one, it means the chip has been installed, and a sound is played, an object that depicts the computer's startup screen is moved to the scene, and a message is printed.
If variable C1# does not equal one, then the third statement is ignored, and a message is printed telling the player that he doesn't have the chip.
If the player did not enter the word "computer," then the second statement is ignored. The program then continues down to the next nested statement, which checks to see if the player has entered the word "chip." If he has, then another statement checks to see if the player has the chip.
If the player does have the chip, then a sound is played, the chip is moved to STORAGE@, the variable C1# is set to one, and a message is displayed telling the player that the chip has been installed. Now if the player enters the words "use" and "computer", the computer will start up.
--------------------------
You could also have additional statements nested in the scene "use" code, to handle specific things the player might be likely to use, such as circuit that doesn't fit, a tool, a disk, etc.
--------------------------
Notice that if the player enters the word "use", but has not entered "computer" or "chip," then the entire section of code closes with END. You should then have a statement in the global code that provides the default response for anything unusual that the player tries to use:
IF{TEXT$=USE}THEN
PRINT{That doesn't work.}
EXIT
----------------------------------------------
Until recently, I was unaware of any simple way to retrieve the number stored in a variable. In my earlier games, I used the following method:
For instance, if you want to find out how much money the player has whenever he types in a dollar sign. Let's say you are using variable M1# to represent the money the player has. As he goes through the game, he spends some and finds some. Adding and subtracting is easy, but finding out the total is a real problem. You can only find the value of the variable like this:
IF{TEXT$=$}THEN
IF{M1#<1}OR{CASH>PLAYER@}THEN
PRINT{You don't have any money.}
EXIT
IF{M1#=1}THEN
PRINT{You have $1.}
EXIT
IF{M1#=2}THEN
PRINT{You have $2.}
EXIT
IF{M1#=3}THEN
PRINT{You have $3.}
EXIT
IF{M1#=4}THEN
PRINT{You have $4.}
EXIT
(...etc, etc, etc.)
As you can see, this is pretty tedious, and worse yet, it takes up a lot of precious code space. Remember, you only have a limited amount of room for code in each scene, and in the global code. If you want the player's cash to go as high as one hundred, you'd need one hundred IF/THEN statements to find out how much he has!! This is why I've limited the cash in my games to a maximum of $10. The player can only find or earn more money if his cash reserves fall below a certain amount.
------------
UPDATE!
------------
Shortly after I released version 1.0 of this tutorial, I was informed that there IS a simple way to print the value of a variable. For some reason this information was not in the official World Builder manual. Just use the PRINT feature, and the variable name, like this:
PRINT{M1#}
Unfortunately, this too has a slight limitation, since it can only print out the number. To make it part of a sentence, you have to do this:
IF{TEXT$=$}THEN
IF{M1#<1}OR{CASH>PLAYER@}THEN
PRINT{You don't have any cash.}
EXIT
PRINT{You have}
PRINT{M1#}
PRINT{dollars.}
EXIT
When the player enters a dollar sign, this is what will be printed in the text window:
You have
470 (or whatever the current amount is)
dollars.
A big thanks to Bubrick@aol.com, aka Steven Merrill for telling me about this method of printing out the value of a variable!